package jee.boot.module.authority.service;

import jee.boot.common.basic.CrudService;
import jee.boot.entity.system.Filter;
import jee.boot.common.standard.AuthorityHandler;
import jee.boot.common.utils.StringUtils;
import jee.boot.entity.auth.*;
import jee.boot.module.authority.dao.*;
import jee.boot.entity.auth.AuthConstant;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Caching;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 原子权限
 */
@Service
public class AuthorityService extends CrudService<AuthorityDao, Authority> {
    @Autowired
    private SbjAuthDao sbjAuthDao;
    @Autowired
    private AuthEntityDao authEntityDao;
    @Autowired
    private ResourceService resourceService;
    @Autowired
    private ModelDataService modelDataService;
    @Autowired
    private ColumnService columnService;
    @Autowired
    private RowSetService rowSetService;
    @Autowired
    private CellSetService cellSetService;
    @Autowired
    private RowSetItemDao rowSetItemDao;
    @Autowired
    private RoleDao roleDao;
    @Autowired
    private AuthEntityService authEntityService;

    @Override
    public Authority get(Authority entity) {
        Authority authority = super.get(entity);
        // 根据主体ID查询所有原子权限
        List<SbjAuth> sbjAuthList = super.getOneToMany(sbjAuthDao, authority, new SbjAuth(), "authority");
        if (sbjAuthList.size() > 0) {
            Role role = new Role();
            role.addFilter(new Filter("id", "in", getBasicSbjIdListByType(AuthConstant.AUTH_SBJ_TYPE_ROLE, sbjAuthList)));
            authority.setRoleList(roleDao.findList(role));
        }
        return authority;
    }

    /**
     * 补充一对多数据
     *
     * @param entity
     */
    public void getMany(Authority entity) {
        // 根据组ID查询所有权限实体
        List<AuthEntity> list = super.getOneToMany(authEntityDao, entity, new AuthEntity(), "authority");
        // 重置Entity
        authEntityService.resetEntity(new AuthEntity(), entity, list);



    }

    /**
     * 更新ResourceList
     *
     * @param entity
     */
    @Caching(evict = {
            @CacheEvict(value = AuthorityHandler.USER_AUTHORITY_KEY, allEntries = true)
    })
    public void updateResourceList(Authority entity) {
        updateItemList(entity, entity.getResourceList(), AuthConstant.AUTH_ENTITY_TYPE_RESOURCE);
    }

    /**
     * 更新TreeNodeList
     *
     * @param entity
     */
    @Caching(evict = {
            @CacheEvict(value = AuthorityHandler.USER_AUTHORITY_KEY, allEntries = true)
    })
    public void updateTreeNodeList(Authority entity) {
        updateItemList(entity, entity.getTreeNodeList(), AuthConstant.AUTH_ENTITY_TYPE_TREE_NODE);
    }


    /**
     * 更新子表关联数据
     *
     * @param entity
     * @param entityList
     * @param entityType
     */
    private void updateItemList(Authority entity, List<AuthEntity> entityList, String entityType) {
        List<AuthEntity> list = new ArrayList<>();
        // 保存所有的资源关联
        if (entityList != null) {
            for (AuthEntity resource : entityList) {
                resource.setEntityType(entityType);
                resource.setEntityId(resource.getEntityId());
                resource.setAuthority(new Authority(entity.getId()));
                resource.preInsert();
                list.add(resource);
            }
        }
        // 删除已存在的关联数据
        AuthEntity del = new AuthEntity();
        del.setAuthority(entity);
        del.setEntityType(entityType);
        del.setControlDomain(null);//置空,否则resource数据删除不掉
        authEntityDao.deleteByAuthEntity(del);
        // 插入新的关联数据
        authEntityDao.batchInsert(list);
    }

    @Caching(evict = {
            @CacheEvict(value = AuthorityHandler.USER_AUTHORITY_KEY, allEntries = true)
    })
    @Override
    public void delete(Authority entity) {
        //删除实体表数据,RowSet,RowSetItem,CellSet数据
        authEntityService.deleteEntityByAuthEntity(new AuthEntity(entity));
        // 删除已存在的关联数据
        AuthEntity del = new AuthEntity();
        del.setAuthority(entity);
        authEntityDao.deleteByAuthEntity(del);
        // 删除 原子权限
        super.delete(entity);
    }

    /**
     * 复制权限配置
     *
     * @param entity
     */
    public void copy(Authority entity) {
        Authority src = get(entity);
        // 根据组ID查询所有权限实体
        List<AuthEntity> list = super.getOneToMany(authEntityDao, entity, new AuthEntity(), "authority");
        if (list != null && !list.isEmpty()) {
            // 复制主表
            copyHead(src);
            // 复制RowSet+RowSetItem表
            copyRowSet(src, list);
            // 复制关系表
            copyAuthEntity(src, list);
        }
    }

    private void copyRowSet(Authority src, List<AuthEntity> list) {
        List<AuthEntity> authRowSetList = authEntityService.getBasicObjIdListByType(AuthConstant.AUTH_ENTITY_TYPE_ROW_SET, list);
        if (authRowSetList != null && !authRowSetList.isEmpty()) {
            List<RowSet> rowSets = authEntityService.getRowSetList(authRowSetList);
            if (!rowSets.isEmpty()) {
                rowSets.stream().forEach(rowSet -> {
                    List<AuthEntity> collect = authRowSetList.stream().filter(authEntity -> StringUtils.equals(rowSet.getId(), authEntity.getEntityId())).collect(Collectors.toList());
                    // 正常这个里的collect只会有一个
                    rowSetService.save(rowSet);
                    // 更换关系表的rowSetId
                    collect.get(0).setEntityId(rowSet.getId());
                });
            }

        }
    }

    /**
     * 复制所有关联的资源
     *
     * @param src
     * @param list
     */
    private void copyAuthEntity(Authority src, List<AuthEntity> list) {
        if (list != null && !list.isEmpty()) {
            list.forEach(authEntity -> {
                authEntity.setAuthority(src);
            });
            authEntityService.batchSave(list);
        }
    }

    /**
     * 复制主表,直接存储新数据即可,原始id会被替换
     *
     * @param src
     */
    private void copyHead(Authority src) {
        src.setCode(src.getCode() + "-Copy");
        src.setNo(src.getNo() + "-Copy");
        src.setName(src.getName() + "-Copy");
        save(src);
    }

    /**
     * 根据关联表的数据按类型取出所有的权限主体entity的id
     *
     * @param type
     * @param list
     * @return
     */
    private List<String> getBasicSbjIdListByType(String type, List<SbjAuth> list) {
        return list.stream()
                .filter(d -> StringUtils.equals(type, d.getSbjType()))
                .map(d -> d.getSbj().getId())
                .collect(Collectors.toList());
    }
}
